﻿
using System ;
using System.ComponentModel ;
using System.Drawing ;
using System.Windows.Forms ;
using System.Diagnostics ;

using MskEdit.Msk.Model ;


namespace MskEdit.Msk.Frontend
{
    public partial class MskFieldUserControl : UserControl
    {
        #region Private data

        private MskLineKey  mskLineKey_ ;
        private int         fieldLen_ ;
        private Point       fieldLocation_ ; // In char pos ( row/col )
        private bool        isSelected_ ;
        
        #endregion

        #region Private members        
        
        private int getCaptionLength() {
            int captionLength = captionLabel.Text.Length ;
            string lastCaptionLetter = captionLabel.Text.Substring( captionLength - 1, 1 ) ;

            if ( lastCaptionLetter.Equals( "#" ) )
                -- captionLength ; 
                
            return captionLength ;                            
        }
        
        
        private void setIsSelected( bool isSelected ) {
            isSelected_ = isSelected ;
            this.BorderStyle = isSelected ? BorderStyle.FixedSingle : BorderStyle.None ;
        }
 
 
        #endregion

        #region Private event handlers

        private void HandleValueTextBoxKeyPress( object sender, KeyPressEventArgs e ) {
            e.Handled = true ; // Disallow typing although enabled style 
        }
        
        
        private void HandleCaptionTextBoxEnter( object sender, EventArgs e ) {
            if ( RadioClick != null )
                RadioClick.Invoke( this ) ;
        }
        
        
        private void HandleValueTextBoxEnter( object sender, EventArgs e ) {
            if ( RadioClick != null )
                RadioClick.Invoke( this ) ;            
        }
        

        void HandleCaptionLabelClick(object sender, EventArgs e) {
            if ( RadioClick != null )
                RadioClick.Invoke( this ) ;            
        }
        

        void HandleValueLabelClick(object sender, EventArgs e) {
            if ( RadioClick != null )
                RadioClick.Invoke( this ) ;            
        }

        #endregion

        #region Public event declarations

        public delegate void RadioClickEventHandler( MskFieldUserControl mskFieldUserControl ) ;
        public event RadioClickEventHandler RadioClick ;

        #endregion


        #region Private foundation

        public static MskFieldUserControl From( MskLine mskLine, MskFieldGeometer fieldGeometer, Color captionBackColor ) {
        
            MskFieldUserControl mskFieldUserControl = new MskFieldUserControl() ;
            mskFieldUserControl.CaptionBackColor = captionBackColor ;
            mskFieldUserControl.UpdateMskLine( mskLine, fieldGeometer ) ;
            
            return mskFieldUserControl ;
        }
        
        
        public MskFieldUserControl() {
            InitializeComponent() ;
        }         

        #endregion

        #region Public members

        public void updateGeometry( MskFieldGeometer fieldGeometer ) {
            
            int captionLength = getCaptionLength() ;
                        
            this.captionLabel.Location     = fieldGeometer.getCaptionLocation() ;
            this.captionLabel.Size         = fieldGeometer.getCaptionSize( captionLength ) ;

            this.valueLabel.Location       = fieldGeometer.getValueLocation( captionLength ) ;
            this.valueLabel.Size           = fieldGeometer.getValueSize( fieldLen_ ) ;

            this.captionClipPanel.Location = fieldGeometer.getCaptionClipPanelLocation() ;
            this.captionClipPanel.Size     = fieldGeometer.getCaptionClipPanelSize( captionLength ) ;            
                    
            this.Location                  = fieldGeometer.getFieldLocation( fieldLocation_ ) ;
            this.Size                      = fieldGeometer.getFieldSize( captionLength, fieldLen_ ) ;
        }
        
        
        private void assertCaptionLabelInvariants() {
        
            Debug.Assert( this.captionLabel.Name.Equals("captionLabel" ) ) ;
            
            if ( ! string.IsNullOrEmpty(this.captionLabel.Text) )
                Debug.Assert( this.captionLabel.Text.LastIndexOf("#") == this.captionLabel.Text.Length - 1 ) ;

            Debug.Assert( this.captionLabel.BackColor == SystemColors.Control ) ;
            Debug.Assert( this.captionLabel.BorderStyle == BorderStyle.None ) ;
            Debug.Assert( this.captionLabel.Location.X == 0 ) ;
            Debug.Assert( this.captionLabel.Location.Y >= 0 ) ;
        }
        
        
        private void assertCaptionClipPanelInvariants() {
            Debug.Assert( this.captionClipPanel.Name.Equals("captionClipPanel" ) ) ;
            Debug.Assert( this.captionClipPanel.BorderStyle == BorderStyle.None ) ;
            Debug.Assert( this.captionClipPanel.Location.X == 0 ) ;
            Debug.Assert( this.captionClipPanel.Location.Y == 0 ) ;
        }
        
        
        private void assertValueLabelInvariants() {
        
            Debug.Assert( this.valueLabel.Name.Equals("valueLabel" ) ) ;

            if ( ! string.IsNullOrEmpty(this.valueLabel.Text) )
                Debug.Assert( this.valueLabel.Text.LastIndexOf("#") == - 1 ) ;
                
            Debug.Assert( this.valueLabel.BackColor == SystemColors.Window ) ;
            Debug.Assert( this.valueLabel.BorderStyle == BorderStyle.Fixed3D ) ;
            Debug.Assert( this.valueLabel.Location.X > 0 ) ;
            Debug.Assert( this.valueLabel.Location.Y >= 0 ) ;
        }
        
        
        private void assertUpdateMskLineInvariants() {
            assertCaptionLabelInvariants() ;
            assertCaptionClipPanelInvariants() ;
            assertValueLabelInvariants() ;
        }
        
        
        public void UpdateMskLine( MskLine mskLine, MskFieldGeometer fieldGeometer ) {
        
//            assertUpdateMskLineInvariants() ;
        
            this.mskLineKey_ = mskLine.LineKey ;

            this.FieldCaption   = mskLine.Caption ;
            this.FieldLen       = mskLine.Len ;
            this.FieldLocation  = mskLine.XYk ;
            this.FieldValue     = mskLine.FieldName ;

            this.updateGeometry( fieldGeometer ) ;
        }
        
        
        public MskLabelAppearance getCaptionTextBoxApperance() {
            return MskLabelAppearance.From( captionLabel ) ;
        }
        
        
        public MskLabelAppearance getValueTextBoxApperance() {
            return MskLabelAppearance.From( valueLabel ) ;
        }
      
        #endregion

        #region Public properties 

        public string FieldCaption {
            get { return captionLabel.Text ; }
            set { captionLabel.Text = value ; }
        }
        
        
        public string FieldValue {
            get { return valueLabel.Text ; }
            set { valueLabel.Text = value ; }
        }
        
        
        public int FieldLen  {
            get { return fieldLen_ ; }
            set { fieldLen_ = value ; }
        }
        
        
        public Point FieldLocation  {
            get { return fieldLocation_ ; }
            set { fieldLocation_ = value ; }
        }
        
        
        public Color CaptionBackColor {
            get { return captionLabel.BackColor ; }
            set { captionLabel.BackColor = value ; }
        }
        
        public bool IsSelected {
            get { return isSelected_ ; } 
            set { setIsSelected( value ) ; }
        }
        
        
        public MskLineKey MskLineKey {
            get { return mskLineKey_ ; }
        }
        
        #endregion
    }
}
